﻿using System;
using System.Collections.Generic;
using System.Text;
using KSS.Generator.Configuration;
using System.IO;
using KSS.Generator.Schema;

namespace KSS.Generator
{
    class LinqProjectGenerator : ProjectGenerator
    {
        public override string ProjectName
        {
            get { return Template.Project.LinqProjectName; }
        }


        /// <summary>
        /// Generate all special template file
        /// </summary>
        /// <param name="projectConfig"></param>
        /// <param name="templateFile"></param>
        /// <param name="generatedDirectory"></param>
        protected override void GenerateFile(ProjectSetting projectConfig,
                                FileInfo templateFile,
                                DirectoryInfo generatedDirectory)
        {
            switch (templateFile.Name)
            {
                case Template.LinqProject.GeneratedProviderFileName:
                    GenerateProviderFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.LinqProject.CustomProviderFileName:
                    GenerateCustomProviderFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.LinqProject.GeneratedStoredProcProviderFileName:
                    GenerateStoredProcedureFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.LinqProject.CustomStoredProcProviderFileName:
                    GenerateCustomStoredProcedureFile(projectConfig, templateFile, generatedDirectory);
                    break;
            }
        }

        private void GenerateProviderFile(ProjectSetting projectConfig,
                                FileInfo templateFile,
                                DirectoryInfo generatedDirectory)
        {
            // Get entity mapper template file content
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);

            // Mapper file name template
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            string sourceCode = string.Empty;

            // Fill methods to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                StringBuilder sbEntityMethods = new StringBuilder();

                List<Column> primaryColumns = t.DataType.GetPrimaryColumns();
                List<Column> foreignColumns = t.DataType.GetForeignColumns();
                List<Association> foreignAssociations = t.DataType.GetForeignAssociations();

                #region { Get count }

                sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetCount,
                                        t.DataType.Name,
                                        t.Member);

                sbEntityMethods.AppendLine(sourceCode);
                #endregion

                #region { GetByPrimaryKey }
                foreach (Column c in primaryColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetByPrimaryKey,
                                        t.DataType.Name,
                                        c.Name,
                                        GeneratorHelper.GetTypeFromColumn(c),
                                        GeneratorHelper.GenerateLocalVariableName(c.Name),
                                        GeneratorHelper.GenerateLocalVariableName(t.DataType.Name),
                                        t.Member);

                    sbEntityMethods.AppendLine(sourceCode);
                }

                #endregion

                #region { GetByForeignKey }

                foreach (Column c in foreignColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetByForeignKey,
                                       t.DataType.Name,
                                       c.Name,
                                       GeneratorHelper.GetTypeFromColumn(c),
                                       GeneratorHelper.GenerateLocalVariableName(c.Name),
                                       t.Member,
                                       GeneratorHelper.GenerateLocalVariableName(t.DataType.Name));

                    sbEntityMethods.AppendLine(sourceCode);
                }

                #endregion

                #region { GetByForeignKeyEntity }

                foreach (Association a in foreignAssociations)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetByForeignKeyEntity,
                                       t.DataType.Name,
                                       a.ThisKey,
                                       a.Member,
                                       GeneratorHelper.GenerateLocalVariableName(a.Member));

                    sbEntityMethods.AppendLine(sourceCode);
                }

                #endregion

                #region { GetByForeignKeyWithPaging }

                foreach (Column c in foreignColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetByForeignKeyWithPaging,
                                       t.DataType.Name,
                                       c.Name,
                                       GeneratorHelper.GetTypeFromColumn(c),
                                       GeneratorHelper.GenerateLocalVariableName(c.Name),
                                       t.Member,
                                       GeneratorHelper.GenerateLocalVariableName(t.Member));

                    sbEntityMethods.AppendLine(sourceCode);
                }

                #endregion

                #region { GetByForeignKeyEntityWithPaging }

                foreach (Association a in foreignAssociations)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetByForeignKeyEntityWithPaging,
                                       t.DataType.Name,
                                       a.Member,
                                       a.ThisKey,
                                       GeneratorHelper.GenerateLocalVariableName(a.Member));

                    sbEntityMethods.AppendLine(sourceCode);
                }

                #endregion

                #region { GetAll }

                sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetAll,
                                     t.DataType.Name,
                                     t.Member,
                                     GeneratorHelper.GenerateLocalVariableName(t.Member));

                sbEntityMethods.AppendLine(sourceCode);

                #endregion

                #region { GetAllWithPaging }

                sourceCode = string.Format(Template.LinqProject.FunctionTemplate_GetAllWithPaging,
                                    t.DataType.Name,
                                    t.Member,
                                    GeneratorHelper.GenerateLocalVariableName(t.Member));

                sbEntityMethods.AppendLine(sourceCode);
                #endregion

                #region { Add }

                sourceCode = string.Format(Template.LinqProject.FunctionTemplate_Add,
                                    t.DataType.Name,
                                    GeneratorHelper.GenerateLocalVariableName(t.DataType.Name),
                                    t.Member);

                sbEntityMethods.AppendLine(sourceCode);
                #endregion

                #region { Update }

                StringBuilder sbPrimaryKeysComparing = new StringBuilder();
                for (int i = 0; i < primaryColumns.Count; i++)
                {
                    if (i != 0)
                    {
                        sbPrimaryKeysComparing.Append(" && ");
                    }

                    sbPrimaryKeysComparing.Append(
                                string.Format(Template.LinqProject.CommandTemplate_PrimaryKeyComparing,
                                primaryColumns[i].Name,
                                GeneratorHelper.GenerateLocalVariableName(t.DataType.Name)));
                }

                sourceCode = string.Format(Template.LinqProject.FunctionTemplate_Update,
                                    t.DataType.Name,
                                    GeneratorHelper.GenerateLocalVariableName(t.DataType.Name),
                                    t.Member,
                                    sbPrimaryKeysComparing.ToString());

                sbEntityMethods.AppendLine(sourceCode);
                #endregion

                #region { DeleteByPrimaryKey }

                foreach (Column c in primaryColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_DeleteByPrimaryKey,
                                   t.DataType.Name,
                                   c.Name,
                                   GeneratorHelper.GetTypeFromColumn(c),
                                   GeneratorHelper.GenerateLocalVariableName(c.Name),
                                   t.Member);

                    sbEntityMethods.AppendLine(sourceCode);
                }
                #endregion

                #region { DeleteByPrimaryEntity }

                foreach (Column c in primaryColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_DeleteByEntity,
                                   t.DataType.Name,
                                   c.Name,
                                   GeneratorHelper.GenerateLocalVariableName(t.DataType.Name));

                    sbEntityMethods.AppendLine(sourceCode);
                }
                #endregion

                #region { DeleteByForeignKey }

                foreach (Column c in foreignColumns)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_DeleteByForeignKey,
                                   t.DataType.Name,
                                   c.Name,
                                   GeneratorHelper.GetTypeFromColumn(c),
                                   GeneratorHelper.GenerateLocalVariableName(c.Name),
                                   t.Member);

                    sbEntityMethods.AppendLine(sourceCode);
                }
                #endregion

                #region { DeleteByForeignEntity }

                foreach (Association a in foreignAssociations)
                {
                    sourceCode = string.Format(Template.LinqProject.FunctionTemplate_DeleteByForeignEntity,
                                   t.DataType.Name,
                                   a.Type,
                                   a.ThisKey,
                                   GeneratorHelper.GenerateLocalVariableName(a.Type));

                    sbEntityMethods.AppendLine(sourceCode);
                }
                #endregion


                projectConfig.SetPropertyValue(
                            Template.LinqProject.CustomTag_EntityMethods,
                            GeneratorHelper.PlaceOpenClose(sbEntityMethods.ToString()));

                // Fill property in template
                sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write source code to file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, t.DataType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateCustomProviderFile(ProjectSetting projectConfig,
                                FileInfo templateFile,
                                DirectoryInfo generatedDirectory)
        {
            /*
            // Get entity mapper template file content
                        string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            
                        // Mapper file name template
                        string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);
            
            
                        // Fill methods to template
                        foreach (Table t in Context.DatabaseSchema.Tables)
                        {
                            // Fill property in template
                            string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);
            
                            // Write source code to file
                            string generatedFilePath = string.Format("{0}\\{1}",
                                        generatedDirectory.FullName,
                                        string.Format(fileNameFormat, t.DataType.Name));
            
                            GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
                        }*/
            
        }

        protected void GenerateStoredProcedureFile(ProjectSetting projectConfig,
                                FileInfo templateFile,
                                DirectoryInfo generatedDirectory)
        {
            /*
            // Get entity mapper template file content
                        string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            
                        // Mapper file name template
                        string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);
            
                        // Store methods
                        StringBuilder sbStoredProcMethods = new StringBuilder();
            
                        // Fill methods to template
                        foreach (Function f in Context.DatabaseSchema.Functions)
                        {
                            GenerateStoreMethod(f, sbStoredProcMethods);
                        }
            
                        projectConfig.SetPropertyValue(
                                        Template.LinqProject.CustomTag_StoredProcedureMethods,
                                        GeneratorHelper.PlaceOpenClose(sbStoredProcMethods.ToString()));
            
                        // Fill property in template
                        string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);
            
                        // Write source code to file
                        string generatedFilePath = string.Format("{0}\\{1}",
                                    generatedDirectory.FullName,
                                    string.Format(fileNameFormat, string.Empty));
            
                        GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);*/
            
        }

        protected void GenerateCustomStoredProcedureFile(ProjectSetting projectConfig,
                                FileInfo templateFile,
                                DirectoryInfo generatedDirectory)
        {
            /*
            // Get entity mapper template file content
                        string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            
                        // Mapper file name template
                        string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);
            
                        // Fill property in template
                        string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);
            
                        // Write source code to file
                        string generatedFilePath = string.Format("{0}\\{1}",
                                    generatedDirectory.FullName,
                                    string.Format(fileNameFormat, string.Empty));
            
                        GeneratorHelper.WriteToFile(generatedFilePath, sourceCode, true);*/
            
        }

    }
}
